package org.dna.metronomo.persistence.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;
import org.dna.metronomo.persistence.Activity;
import org.dna.metronomo.persistence.ActivityMapper;
import org.dna.metronomo.persistence.IActivityDAO;
import org.dna.metronomo.persistence.Job;
import org.dna.metronomo.persistence.JobMapper;
import org.dna.metronomo.persistence.PersistenceException;

public class IBatisActivityDAO extends IBatisMetronomoDAO 
	implements IActivityDAO {
	
	public List<Activity> allActivities() throws PersistenceException {
		return executeInSession(new SessionExecutor<List<Activity>>() {

			@SuppressWarnings("unchecked")
			public List<Activity> execute(SqlSession session) {
				return (List<Activity>) session
						.selectList("org.dna.metronomo.persistence.ActivityMapper.listAll");
			}
		});
	}

	public void addNewActivity(final Activity activity)
			throws PersistenceException {
		executeInSession(new SessionExecutor<Void>() {
			public Void execute(SqlSession session) {
				ActivityMapper mapper = session.getMapper(ActivityMapper.class);
				mapper.insert(activity);
				return null;
			}
		});
	}

	public void deleteActivityByExample(final Activity activity) {
		executeInSession(new SessionExecutor<Void>() {
			public Void execute(SqlSession session) {
				if (activity.getJobs() == null || activity.getJobs().isEmpty()) {
					session.delete(
									"org.dna.metronomo.persistence.ActivityMapper.deleteByExample",
									activity);
				} else {
					Map param = new HashMap();
					param.put("activity", activity);
					param.put("status", STATUS_DELETED);
					session.update("org.dna.metronomo.persistence.ActivityMapper.updateStatusByExample", param);
				}
				return null;
			}
		});
	}

	public void deleteActivityByID(final int id) {
		executeInSession(new SessionExecutor<Void>() {
			public Void execute(SqlSession session) {
				Activity activity = new QueryByIDExecutor(id).execute(session);
				ActivityMapper mapper = session.getMapper(ActivityMapper.class);
                if (activity == null) {
                    return null;
                }

				if (activity.getJobs() == null || activity.getJobs().isEmpty()) {
					mapper.deleteByID(id);
				} else {
					mapper.updateStatusByID(id, STATUS_DELETED);
				}
				return null;
			}
		});
	}

	public void update(final Activity activity) throws PersistenceException {
		executeInSession(new SessionExecutor<Void>() {
			public Void execute(SqlSession session) {
				ActivityMapper mapper = session.getMapper(ActivityMapper.class);
				mapper.update(activity);
				return null;
			}
		});
	}

	public void addJobToActivity(final Job job, final Activity activity)
			throws PersistenceException {
		executeInSession(new SessionExecutor<Void>() {
			public Void execute(SqlSession session) {
				Map<String, Object> params = new HashMap<String, Object>();
				params.put("activity", activity);
				params.put("job", job);
				session.insert(
								"org.dna.metronomo.persistence.JobMapper.addJobToActivity",
								params);
				return null;
			}
		});
	}

	public void updateJob(final Job job) throws PersistenceException {
		executeInSession(new SessionExecutor<Void>() {
			public Void execute(SqlSession session) {
				JobMapper mapper = session.getMapper(JobMapper.class);
				mapper.update(job);
				return null;
			}
		});
	}

	public List<Activity> queryActivityByExample(final Activity activity)
			throws PersistenceException {
		return executeInSession(new SessionExecutor<List<Activity>>() {

			@SuppressWarnings("unchecked")
			public List<Activity> execute(SqlSession session) {
				return session.selectList(
								"org.dna.metronomo.persistence.ActivityMapper.queryByExample",
								activity);
			}
		});
	}

	public Activity queryActivityByID(final int id) {
		return executeInSession(new QueryByIDExecutor(id));
	}
	
	private static class QueryByIDExecutor implements SessionExecutor<Activity> {
		int id;
		
		public QueryByIDExecutor(int id) {
			this.id = id;
		}
		
		@SuppressWarnings("unchecked")
		public Activity execute(SqlSession session) {
			Activity act = (Activity) session.selectOne(
							"org.dna.metronomo.persistence.ActivityMapper.queryByID",
							this.id);
			return act;
		}
	} 
}
